#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <termios.h>
#include <pthread.h>
#include "include/data_hand.h"
#include "include/sem.h"
#include <semaphore.h>
#include "include/data_global.h"
#include "include/thread.h"


int dev_uart_fd;
struct env_info serial_data = {};
pthread_mutex_t recvdata_lock;


void *recv_hand(void *fd); //接收数据线程
void *DataUpload_hand(void *arg); //数据上传线程
void *DataSave_hand(void *arg); //数据保存线程
void *pthread_client_request(void *arg); //客户端请求线程

struct prodcons
{
    // 缓冲区相关数据结构
    int buffer[5]; /* 实际数据存放的数组*/
    pthread_mutex_t lock; /* 互斥体lock 用于对缓冲区的互斥操作 */
    int readpos, writepos; /* 读写指针*/
    pthread_cond_t notempty; /* 缓冲区非空的条件变量 */
    pthread_cond_t notfull; /* 缓冲区未满的条件变量 */
};

struct prodcons buffer;

/* 初始化缓冲区结构 */
void init(struct prodcons *b)
{
    pthread_mutex_init(&b->lock, NULL);
    pthread_cond_init(&b->notempty, NULL);
    pthread_cond_init(&b->notfull, NULL);
    b->readpos = 0;
    b->writepos = 0;
    srand((int)time(0));
}

/*功能：串口初始化
  参数：串口设备文件描述符
 */
void serial_init(int fd)
{
    struct termios options;
    tcgetattr(fd, &options);
    options.c_cflag |= ( CLOCAL | CREAD );
    options.c_cflag &= ~CSIZE;
    options.c_cflag &= ~CRTSCTS;
    options.c_cflag |= CS8;
    options.c_cflag &= ~CSTOPB;
    options.c_iflag |= IGNPAR;
    options.c_iflag &= ~(ICRNL | IXON);
    options.c_oflag = 0;
    options.c_lflag = 0;

    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);
    tcsetattr(fd,TCSANOW,&options);
}



int main(void)
{
    pthread_t save_thread;
    pthread_t upload_thread;
    pthread_t recv_thread;
    pthread_t clientreq_thread;

    sem_t sem;
	init_mem(); //初始化共享内存
	fisrt_init_sem(); //初始化信号灯

    if(sem_init(&sem, 0, 0) < 0) //初始化信号量
    {
        perror("fail to sem_init");
        return -1;
    }

    if(pthread_mutex_init(&recvdata_lock, NULL) < 0) //线程互斥锁初始化
    {
        perror("fail to mutux_init");
        return -1;
    }
    
    printf("on open\n");
    if( (dev_uart_fd = open("/dev/ttyUSB0", O_RDWR, 0666) ) < 0)
    {
        perror("fail to open ttyUSB0");
        exit(-1);
    }
    serial_init(dev_uart_fd); //串口初始化
    puts("serial_init behind");
    //init(&buffer); //初始化同步锁
    puts("after init buffer");


    if(pthread_create(&save_thread, NULL, DataSave_hand, NULL) < 0)
    {
        perror("fail to create save_thread");
        return -1;
    }

    if(pthread_create(&upload_thread, NULL, DataUpload_hand, NULL) < 0)
    {
        perror("fail to create upload_thread");
        return -1;
    }

    if(pthread_create(&recv_thread, NULL, recv_hand, NULL) < 0) 
    { 
        perror("fail to create recv_thread");
        return -1;
    }
    if(pthread_create(&clientreq_thread, NULL, pthread_client_request, NULL) < 0)
    {

        perror("fail to create clientreq_thread");
        return -1;
    }




    pthread_join(clientreq_thread, NULL);

    pthread_join(recv_thread, NULL);
    pthread_join(save_thread, NULL);
    pthread_join(upload_thread, NULL);

	return 0;
}

void *DataUpload_hand(void *arg)
{

   // pthread_cond_wait(&buffer.notempty, (pthread_mutex_t *)NULL);
    puts("upload_thread : sleep ...");
    sleep(2);
    puts("save now");
    while(1)
    {   
        sem_p(semid,0);
        /*******************锁**********/
        pthread_mutex_lock(&recvdata_lock);
        *shm_buf = serial_data;
        pthread_mutex_unlock(&recvdata_lock);
        /*******************开锁**********/
        sem_v(semid,0);
        sleep(1);
    }

//    pthread_cond_destroy(&buffer.notempty);


}

void *DataSave_hand(void *arg) //数据保存线程
{
    int i = 0;
    linkhead_t *l = create_linklist();
    sleep(2);


    while(1)
    {
        i ++;
        /*******************锁**********/
        pthread_mutex_lock(&recvdata_lock);
        insert_linklist(0, serial_data, l);
        pthread_mutex_unlock(&recvdata_lock);
        /*******************开锁**********/
        if(i == 10)
        {
            i = 0;
            printf("l -> len : %d\n", l->len);
            show_linklist(l);

            
            clear_link(l);
        }
        sleep(1);

    }


}

void *recv_hand(void *fd)
{
	while(1)
	{
		printf("on read\n");

        /*******************锁**********/
        pthread_mutex_lock(&recvdata_lock);
    	read(dev_uart_fd, &serial_data, sizeof(struct env_info));
        pthread_mutex_unlock(&recvdata_lock);
        /*******************开锁**********/

		printf("behind read\n");
//     	printf("x:%d y:%d z:%d\n", serial_data.x, serial_data.y, serial_data.z);
	//   pthread_cond_signal(&buffer.notempty);
     	sleep(1);	
	}
}
